﻿using System;
using System.Data.Entity;
using System.Data.Entity.Validation;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using TCC.ControleFluxoDeCaixa.Model.Entities;
using TCC.ControleFluxoDeCaixa.Model.Fluxo;
using TCC.ControleFluxoDeCaixa.Model.Fluxo.Credito;
using TCC.ControleFluxoDeCaixa.Model.Gerenciadores;

namespace TCC.ControleFluxoDeCaixa.Test
{
    [TestClass]
    public class UnidadeDeTesteCartaoDeCredito
    {
        [TestInitialize]
        public void SetDataBaseInitialize()
        {
            Database.SetInitializer(new DropCreateDatabaseIfModelChanges<FluxoDeCaixaContext>());
        }
        
        [TestMethod]
        public void TestarCricaoContaCredito()
        {
            var contexto = FluxoContextFactory.GetInstance().Create();
            var contaCredito = new ContaCredito
            {
                Bandeira = contexto.BandeiraCreditos.Find(1),
                ContaVinculada = contexto.ContaFinanceiraBancarias.Find(2),
                DiaDoVencimento = 10,
                ValorLimite = 5000,
                Validade = DateTime.Now,     
                TitularDoCartao = "Diogo A.Souza",
                Nome = "Ourocard",
                ValorAnuidade = 2000,
                Numero = "4984235037943812",
                DigitoVerificador = "942",
                Usuario = contexto.Usuarios.Find(1)
         
            };

            try
            {
                contexto.ContasCredito.Add(contaCredito);
                contexto.SaveChanges();
            }
            catch (DbEntityValidationException ex)
            {
                foreach (var validationError in 
                    ex.EntityValidationErrors.
                    SelectMany(validationErrors => validationErrors.ValidationErrors))
                {
                    Console.WriteLine("Property: {0} Error: {1}", 
                        validationError.PropertyName, validationError.ErrorMessage);
                }
                throw;
            }


        }

        [TestMethod]
        public void TesteAdicionarFeriado()
        {
            var contexto = FluxoContextFactory.GetInstance().Create();
            var feriadoDataVariavel = new FeriadoDataVariavel
            {
                Data = new DateTime(2015, 5, 11),
                Descricao = "Teste data variavel"
            };
            contexto.FeriadosDataVariavel.Add(feriadoDataVariavel);
            contexto.SaveChanges();

            var feriadoDataFixa = new FeriadoDataFixa()
            {
                Dia = 12,
                Mes = 5,
                Descricao = "Teste data fixa"
            };
            contexto.FeriadosDataFixa.Add(feriadoDataFixa);
            contexto.SaveChanges();
        }
        [TestMethod]
        public void TesteContaCreditoLancamentoParcelasVencimentos()
        
        {
            var contaCredito = new ContaCredito {DiaDoVencimento = 10, QtdDiasPeriodoFechamento = 10};
            {
                var lancamento = contaCredito.LancamentoCartaoCredito(500, null, new DateTime(2015, 2, 25), 5, "Teste");

                var vencimentoFaturaParcela1 = new DateTime(2015, 3, 10); //Não é feriado
                var vencimentoFaturaParcela2 = new DateTime(2015, 4, 10); //Não é feriado
                var vencimentoFaturaParcela3 = new DateTime(2015, 5, 11); //Segunda
                var vencimentoFaturaParcela4 = new DateTime(2015, 6, 10); //Não é feriado
                var vencimentoFaturaParcela5 = new DateTime(2015, 7, 10); //Não é feriado

                Assert.AreEqual(lancamento.Movimentos.Count, 5);
                var parcelas = lancamento.Movimentos.OrderBy(m => m.DataDoMovimento).ToArray();
                Assert.AreEqual(vencimentoFaturaParcela1, parcelas[0].DataDoMovimento);
                Assert.AreEqual(vencimentoFaturaParcela2, parcelas[1].DataDoMovimento);
                Assert.AreEqual(vencimentoFaturaParcela3, parcelas[2].DataDoMovimento);
                Assert.AreEqual(vencimentoFaturaParcela4, parcelas[3].DataDoMovimento);
                Assert.AreEqual(vencimentoFaturaParcela5, parcelas[4].DataDoMovimento);
            }
            {
                var lancamento = contaCredito.LancamentoCartaoCredito(500, null, new DateTime(2012, 2, 29), 5, "Teste");

                var vencimentoFaturaParcela1 = new DateTime(2012, 3, 12); //Não é feriado
                var vencimentoFaturaParcela2 = new DateTime(2012, 4, 10); //Não é feriado
                var vencimentoFaturaParcela3 = new DateTime(2012, 5, 10); //Segunda
                var vencimentoFaturaParcela4 = new DateTime(2012, 6, 11); //Não é feriado
                var vencimentoFaturaParcela5 = new DateTime(2012, 7, 10); //Não é feriado

                Assert.AreEqual(5, lancamento.Movimentos.Count);
                
                var parcelas = lancamento.Movimentos.OrderBy(m => m.DataDoMovimento).ToArray();
                Assert.AreEqual(vencimentoFaturaParcela1, parcelas[0].DataDoMovimento);
                Assert.AreEqual(vencimentoFaturaParcela2, parcelas[1].DataDoMovimento);
                Assert.AreEqual(vencimentoFaturaParcela3, parcelas[2].DataDoMovimento);
                Assert.AreEqual(vencimentoFaturaParcela4, parcelas[3].DataDoMovimento);
                Assert.AreEqual(vencimentoFaturaParcela5, parcelas[4].DataDoMovimento);
            }
            {
                var lancamento = contaCredito.LancamentoCartaoCredito(500, null, new DateTime(2012, 3, 12), 5, "Teste");

                var vencimentoFaturaParcela1 = new DateTime(2012, 4, 10); //Não é feriado
                var vencimentoFaturaParcela2 = new DateTime(2012, 5, 10); //Não é feriado
                var vencimentoFaturaParcela3 = new DateTime(2012, 6, 11); //Segunda
                var vencimentoFaturaParcela4 = new DateTime(2012, 7, 10); //Não é feriado
                var vencimentoFaturaParcela5 = new DateTime(2012, 8, 10); //Não é feriado

                Assert.AreEqual(5, lancamento.Movimentos.Count);

                var parcelas = lancamento.Movimentos.OrderBy(m => m.DataDoMovimento).ToArray();
                Assert.AreEqual(vencimentoFaturaParcela1, parcelas[0].DataDoMovimento);
                Assert.AreEqual(vencimentoFaturaParcela2, parcelas[1].DataDoMovimento);
                Assert.AreEqual(vencimentoFaturaParcela3, parcelas[2].DataDoMovimento);
                Assert.AreEqual(vencimentoFaturaParcela4, parcelas[3].DataDoMovimento);
                Assert.AreEqual(vencimentoFaturaParcela5, parcelas[4].DataDoMovimento);
            }
            {
                contaCredito = new ContaCredito { DiaDoVencimento = 10, QtdDiasPeriodoFechamento = 0 };
                var lancamento = contaCredito.LancamentoCartaoCredito(500, null, new DateTime(2012, 3, 12), 5, "Teste");

                var vencimentoFaturaParcela1 = new DateTime(2012, 4, 10); //Não é feriado
                var vencimentoFaturaParcela2 = new DateTime(2012, 5, 10); //Não é feriado
                var vencimentoFaturaParcela3 = new DateTime(2012, 6, 11); //Segunda
                var vencimentoFaturaParcela4 = new DateTime(2012, 7, 10); //Não é feriado
                var vencimentoFaturaParcela5 = new DateTime(2012, 8, 10); //Não é feriado

                Assert.AreEqual(5, lancamento.Movimentos.Count);

                var parcelas = lancamento.Movimentos.OrderBy(m => m.DataDoMovimento).ToArray();
                Assert.AreEqual(vencimentoFaturaParcela1, parcelas[0].DataDoMovimento);
                Assert.AreEqual(vencimentoFaturaParcela2, parcelas[1].DataDoMovimento);
                Assert.AreEqual(vencimentoFaturaParcela3, parcelas[2].DataDoMovimento);
                Assert.AreEqual(vencimentoFaturaParcela4, parcelas[3].DataDoMovimento);
                Assert.AreEqual(vencimentoFaturaParcela5, parcelas[4].DataDoMovimento);
            }
        }
        [TestMethod]
        public void TesteContaCreditoLancamentoFechamentos()
        {
            var contaCredito = new ContaCredito { DiaDoVencimento = 10, QtdDiasPeriodoFechamento = 10 };
            
            var dataCompra1 = new DateTime(2015, 2, 20);
            var fechamentoEsperadoCompra1 = new DateTime(2015, 2, 28);
            var fechamentoCompra1 = contaCredito.ObterDiaFechamentoFatura(dataCompra1);

            Assert.AreEqual(fechamentoEsperadoCompra1, fechamentoCompra1);

            var dataCompra2 = new DateTime(2015, 3, 2);
            var fechamentoEsperadoCompra2 = new DateTime(2015, 3, 31);
            var fechamentoCompra2 = contaCredito.ObterDiaFechamentoFatura(dataCompra2);

            Assert.AreEqual(fechamentoEsperadoCompra2, fechamentoCompra2);

            var dataCompra3 = new DateTime(2015, 3, 31);
            var fechamentoEsperadoCompra3 = new DateTime(2015, 5, 1);
            var fechamentoCompra3 = contaCredito.ObterDiaFechamentoFatura(dataCompra3);
            
            Assert.AreEqual(fechamentoEsperadoCompra3, fechamentoCompra3);
        }


    }
}
